#include "SpellManager.h"

SpellManager* SpellManager::spellManagerPtr = 0;

SpellManager::SpellManager()
{
	
}

SpellManager::~SpellManager()
{
	ReleaseCOM(spells[0].spellTex);
}
SpellManager* SpellManager::instance()
{
	if(spellManagerPtr == 0)
	{
		spellManagerPtr = new SpellManager();
		SpellManager::instance()->loadSpells();
	}	
	
	return spellManagerPtr;
}

void SpellManager::loadSpells()
{
	//hard coded, technically shd be read from a file but for the sake of time saving, they are hard coded	
	spells[0].ID = 1;
	spells[0].name = "Fireball R1";
	spells[0].damage = 9;
	spells[0].duration = 0.0f;
	spells[0].frequency =0.0f;
	spells[0].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[0].texFilename = "FireBall01.png";
	spells[0].type = DIRECTDAMAGE;
	spells[0].target = OPPONENT;

	HR(D3DXCreateTextureFromFile(gd3dDevice, "FireBall01.png", &(spells[0].spellTex) ));

	spells[1].ID = 2;
	spells[1].name = "Fireball R2";
	spells[1].damage = 18;
	spells[1].duration = 0;
	spells[1].frequency = 0;
	spells[1].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[1].texFilename = "FireBall01.png";
	spells[1].type = DIRECTDAMAGE;
	spells[1].target = OPPONENT;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "FireBall01.png", &(spells[1].spellTex) ));

	spells[2].ID = 3;
	spells[2].name = "Fireball R3";
	spells[2].damage = 30;
	spells[2].duration = 0;
	spells[2].frequency = 0;
	spells[2].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[2].texFilename = "FireBall01.png";
	spells[2].type = DIRECTDAMAGE;
	spells[2].target = OPPONENT;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "FireBall01.png", &(spells[2].spellTex) ));

	spells[3].ID = 13;
	spells[3].name = "Purification";
	spells[3].damage = -24;
	spells[3].duration = 0;
	spells[3].frequency = 0;
	spells[3].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[3].texFilename = "FireBall01.png";
	spells[3].type = HEALING;
	spells[3].target = SELF;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "FireBall01.png", &(spells[3].spellTex) ));

	//Water Spells----------------------------------------------------------------------
	spells[4].ID = 16;
	spells[4].name = "Rising Tide";
	spells[4].damage = 3;
	spells[4].duration = 15;
	spells[4].frequency = 3;
	spells[4].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[4].texFilename = "WaterBall01.png";
	spells[4].type = DOT;
	spells[4].target = OPPONENT;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "WaterBall01.png", &(spells[4].spellTex) ));

	spells[5].ID = 17;
	spells[5].name = "Cure Water R2";
	spells[5].damage = -18;
	spells[5].duration = 0;
	spells[5].frequency = 0;
	spells[5].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[5].texFilename = "WaterBall01.png";
	spells[5].type = HEALING;
	spells[5].target = SELF;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "WaterBall01.png", &(spells[5].spellTex) ));

	spells[6].ID = 14;
	spells[6].name = "Cure Water R1";
	spells[6].damage = -8;
	spells[6].duration = 0;
	spells[6].frequency = 0;
	spells[6].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[6].texFilename = "WaterBall01.png";
	spells[6].type = HEALING;
	spells[6].target = SELF;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "WaterBall01.png", &(spells[6].spellTex) ));

	spells[7].ID = 24;
	spells[7].name = "Cure Water R3";
	spells[7].damage = -24;
	spells[7].duration = 0;
	spells[7].frequency = 0;
	spells[7].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[7].texFilename = "WaterBall01.png";
	spells[7].type = HEALING;
	spells[7].target = SELF;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "WaterBall01.png", &(spells[7].spellTex) ));

	//Wind Spells------------------------------------------------------------------------
	spells[8].ID = 27;
	spells[8].name = "Healing Wind";
	spells[8].damage = -8;
	spells[8].duration = 0;
	spells[8].frequency = 0;
	spells[8].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[8].texFilename = "WindBall01.png";
	spells[8].type = HEALING;
	spells[8].target = SELF;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "WindBall01.png", &(spells[8].spellTex) ));

	spells[9].ID = 30;
	spells[9].name = "Gust";
	spells[9].damage = 15;
	spells[9].duration = 0;
	spells[9].frequency = 0;
	spells[9].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[9].texFilename = "WindBall01.png";
	spells[9].type = DIRECTDAMAGE;
	spells[9].target = OPPONENT;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "WindBall01.png", &(spells[9].spellTex) ));

	spells[10].ID = 36;
	spells[10].name = "Tornado";
	spells[10].damage = 24;
	spells[10].duration = 0;
	spells[10].frequency = 0;
	spells[10].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[10].texFilename = "WindBall01.png";
	spells[10].type = DIRECTDAMAGE;
	spells[10].target = OPPONENT;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "WindBall01.png", &(spells[10].spellTex) ));

	spells[11].ID = 37;
	spells[11].name = "Second Wind";
	spells[11].damage = -14;
	spells[11].duration = 0;
	spells[11].frequency = 0;
	spells[11].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[11].texFilename = "WindBall01.png";
	spells[11].type = HEALING;
	spells[11].target = SELF;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "WindBall01.png", &(spells[11].spellTex) ));

	//Earth Spells----------------------------------------------------------------------
	spells[12].ID = 40;
	spells[12].name = "Tremor";
	spells[12].damage = 9;
	spells[12].duration = 0;
	spells[12].frequency = 0;
	spells[12].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[12].texFilename = "EarthBall01.png";
	spells[12].type = DIRECTDAMAGE;
	spells[12].target = OPPONENT;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "EarthBall01.png", &(spells[12].spellTex) ));

	spells[13].ID = 42;
	spells[13].name = "After Shock";
	spells[13].damage = 15;
	spells[13].duration = 0;
	spells[13].frequency = 0;
	spells[13].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[13].texFilename = "EarthBall01.png";
	spells[13].type = DIRECTDAMAGE;
	spells[13].target = OPPONENT;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "EarthBall01.png", &(spells[13].spellTex) ));

	spells[14].ID = 49;
	spells[14].name = "Earthquake";
	spells[14].damage = 21;
	spells[14].duration = 0;
	spells[14].frequency = 0;
	spells[14].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[14].texFilename = "EarthBall01.png";
	spells[14].type = DIRECTDAMAGE;
	spells[14].target = OPPONENT;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "EarthBall01.png", &(spells[14].spellTex) ));

	spells[15].ID = 43;
	spells[15].name = "Rejuvenate";
	spells[15].damage = -18;
	spells[15].duration = 0;
	spells[15].frequency = 0;
	spells[15].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[15].texFilename = "EarthBall01.png";
	spells[15].type = HEALING;
	spells[15].target = SELF;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "EarthBall01.png", &(spells[15].spellTex) ));

	spells[16].ID = 23;
	spells[16].name = "Tsunami";
	spells[16].damage = -5;
	spells[16].duration = 15;
	spells[16].frequency = 3;
	spells[16].center = D3DXVECTOR3(64.0f, 64.0f, 0.0f);
	spells[16].texFilename = "WaterBall01.png";
	spells[16].type = HOT;
	spells[16].target = SELF;
	HR(D3DXCreateTextureFromFile(gd3dDevice, "WaterBall01.png", &(spells[16].spellTex) ));
}

int SpellManager::getSpellSubscript(int spellID)
{	
	//loop until the id matches
	for(int i = 0; i < MAXSPELLS; i++)
	{
		if(spells[i].ID == spellID )
		{
			return i;
		}
	}

	//default to fireball
	return 0;
}


void SpellManager::addSpell(int id, Player *player)
{
	//make a new spell
	activeSpell spell;

	int spellSubscript = 0;

	//get spell subscript
	spellSubscript = getSpellSubscript(id);
	
	//get spell info
	spell.spellID = spellSubscript;
	spell.pos = D3DXVECTOR3(player->getPlayerPortraitPosX(), 0.0f, 0.0f);
	spell.player = player;
	spell.alive = true;
	spell.finalFrames = false;
	spell.currFrame = 0;
	spell.timeAccum	= 0.0f;
	spell.damage = spells[spellSubscript].damage;
	spell.target = getTarget(spellSubscript, player);
	spell.frequency = spells[spellSubscript].frequency;
	spell.duration = spells[spellSubscript].duration;
	spell.dotAccum = 0.0f;
	spell.dotDrawing = false;

	//add spell to the list
	activeSpellList.push_back(spell);
}

void SpellManager::updateSpell(float dt, Player* targetPos[NUMPLAYERS])
{
	//TO DO: MAKE IT A GLOBAL SO ALL FILES HAVE ACCESS
	float tileWidth = 64.0f;
	
	if(!activeSpellList.empty())
	{
		activeSpellListItr = activeSpellList.begin();

		while(activeSpellListItr != activeSpellList.end())
		{
			//if its a dot only update when the dot is drawing
			if((spells[activeSpellListItr->spellID].type == DOT || spells[activeSpellListItr->spellID].type == HOT) && activeSpellListItr->dotDrawing)
			{
				activeSpellListItr->timeAccum += dt;
			}
			else
			{
				activeSpellListItr->timeAccum += dt;
			}

			if(activeSpellListItr->finalFrames && (spells[activeSpellListItr->spellID].type == DOT || spells[activeSpellListItr->spellID].type == HOT))
			{
				if(activeSpellListItr->dotAccum >= activeSpellListItr->frequency)
				{
					activeSpellListItr->dotDrawing = true;
					targetPos[activeSpellListItr->target]->addHealth(activeSpellListItr->damage);
					activeSpellListItr->dotAccum = 0.0f;
					activeSpellListItr->duration -= activeSpellListItr->frequency;
				}
				else
				{
					activeSpellListItr->dotAccum += dt;
				}

			}

			//once in final frames, do not move
			if(!activeSpellListItr->finalFrames)
			{
				if(activeSpellListItr->target == PLAYER1)
				{
					activeSpellListItr->pos.x -= dt * 500;
				}
				else
				{
					activeSpellListItr->pos.x += dt * 500;
				}
			}
			
			//animate spell
			if(activeSpellListItr->timeAccum >= 1.0f/5.0f )
			{
				if((spells[activeSpellListItr->spellID].type == DOT || spells[activeSpellListItr->spellID].type == HOT) && activeSpellListItr->dotDrawing)
				{
					activeSpellListItr->currFrame++;
					activeSpellListItr->timeAccum = 0.0f;
				}
				else
				{
					activeSpellListItr->currFrame++;
					activeSpellListItr->timeAccum = 0.0f;
				}

				if(activeSpellListItr->target == PLAYER1)
				{
					if(activeSpellListItr->pos.x <= targetPos[activeSpellListItr->target]->getPlayerPortraitPosX() + tileWidth)
						activeSpellListItr->finalFrames = true;
				}
				else if(activeSpellListItr->target == PLAYER2 || activeSpellListItr->target == AIKUN)
				{
					if(activeSpellListItr->pos.x >= targetPos[activeSpellListItr->target]->getPlayerPortraitPosX() - tileWidth)
						activeSpellListItr->finalFrames = true;
				}



				if(activeSpellListItr->finalFrames)  // (activeSpellListItr->player->getPlayerPortraitPosX() - tileWidth))
				{
					//set final frames to true
					//activeSpellListItr->finalFrames = true;

					if(activeSpellListItr->currFrame > 11)
					{
						//if it is a dot do not kill it, but reset its frequency and final frames value, and decrement duration by its frequency
						if(spells[activeSpellListItr->spellID].type != DOT && spells[activeSpellListItr->spellID].type != HOT)
						{	
							targetPos[activeSpellListItr->target]->addHealth(activeSpellListItr->damage);						
							//spell has completed, kill it
							activeSpellListItr->alive = false;								
							activeSpellListItr = activeSpellList.erase(activeSpellListItr);
						}
						else
						{
							//update the frequency time for the dot spell to fire
							//activeSpellListItr->dotAccum += dt;				
			
							//if(activeSpellListItr->dotAccum >= activeSpellListItr->frequency)
                                activeSpellListItr->dotDrawing = false;
								activeSpellListItr->currFrame = 6;

							//its a dot
							if(activeSpellListItr->duration <= 0.0f)
							{								
								activeSpellListItr->alive = false;								
								activeSpellListItr = activeSpellList.erase(activeSpellListItr);
							}
						}						
					}
				}//may not work if we are using ai			
				else
				{				

					if(activeSpellListItr->currFrame > 5 )
						activeSpellListItr->currFrame = 4;
				}
			
			}
			
			activeSpellListItr++;
		}
	}
}

void SpellManager::drawSpell(ID3DXSprite* mSprite)
{
	//TO DO: MAKE IT A GLOBAL SO ALL FILES HAVE ACCESS
	float tileWidth = 64.0f;

	HR(gd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, true));
	
	activeSpellListItr = activeSpellList.begin();

	while(activeSpellListItr != activeSpellList.end())
	{
		//without transformation, image will draw at center of screen
		D3DXMATRIX T, S, Rot;
		D3DXMatrixTranslation(&T, activeSpellListItr->pos.x, activeSpellListItr->pos.y, 0.0f);
		D3DXMatrixScaling(&S, 2.0f, 8.0f, 1.0f); 
		
		D3DXMatrixRotationZ(&Rot, 0.0f);

		if(activeSpellListItr->target == PLAYER1)
		{
			D3DXMatrixRotationZ(&Rot, D3DX_PI);
		}

		HR(mSprite->SetTransform(&(Rot * S * T)));
		int col = activeSpellListItr->currFrame%11;
		int row = activeSpellListItr->currFrame/4;

		// Left, Top, Right, Bottom
		RECT R = {col * tileWidth * 2, (512-(tileWidth * 2 * (row + 1))),  ((col + 1) * tileWidth * 2), (512-(tileWidth * 2 * row))};

		if(spells[activeSpellListItr->spellID].type == DOT && activeSpellListItr->finalFrames)
		{

				if(activeSpellListItr->dotDrawing)
				{
					HR(mSprite->Draw(SpellManager::instance()->spells[activeSpellListItr->spellID].spellTex, &R, &SpellManager::instance()->spells[activeSpellListItr->spellID].center, 0, D3DCOLOR_XRGB(255, 255, 255)));

					//update dotAccum
					//activeSpellListItr->dotAccum = 0.0f;
					//activeSpellListItr->duration -= activeSpellListItr->frequency;
				}
				//else if(activeSpellListItr->currFrame >= 6)
					//HR(mSprite->Draw(SpellManager::instance()->spells[activeSpellListItr->spellID].spellTex, &R, &SpellManager::instance()->spells[activeSpellListItr->spellID].center, 0, D3DCOLOR_XRGB(255, 255, 255)));

				//if(activeSpellListItr->currFrame > 11)
					
		}
		else
		{
			HR(mSprite->Draw(SpellManager::instance()->spells[activeSpellListItr->spellID].spellTex, &R, &SpellManager::instance()->spells[activeSpellListItr->spellID].center, 0, D3DCOLOR_XRGB(255, 255, 255)));
		}

		activeSpellListItr++;
	}
		HR(mSprite->Flush());
		HR(gd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false));	
}

PLAYERID SpellManager::getTarget(int spellID, Player *p)
{
	//using if because we don't have many choices
	//if(spells[getSpellSubscript(spellID)].type == DIRECTDAMAGE || spells[getSpellSubscript(spellID)].type == DOT)
	if(spells[spellID].type == DIRECTDAMAGE || spells[spellID].type == DOT)
	{
		//if player 1 is casting, the target shd be player 2, or vice versa
		if(p->getPlayerID() == PLAYER1)
		{
			if(p->getHuman())
				return PLAYER2;
			else
				return AIKUN;
		}
		else
			return PLAYER1;
	}
	else
	{
		//we know it must be a healing spell, target == self
		return p->getPlayerID();
	}
}